
import request from 'request';
import sha1 from 'sha1';
import events from 'events';
import { exesql } from '../database/db';
import { sendLogToEmail } from './logger';
import cluster from 'cluster';
import {LOCAL_HTTP_SERVER, LOCAL_HTTP_PORT} from '../config/config';

const STATE_PREFIX = '_state';
if (cluster.isWorker) {
    console.log(`wxtoken cluster.isWorker[${cluster.worker.id}]`)
    // 处理事件问题
    var eventMap = new Map();
    // 配置信息数据
    var publicPlatfromList = [];
    // 存放每次appid，srcret生成的token
    var activeAccessTokens = [];
}

export function getPublicPlatfromList() {
    return publicPlatfromList;
}

/**
 * 初始化Token列表
 */
export function initActiveAccessTokens(wxTokenList){
    activeAccessTokens = wxTokenList;
}

/**
 * @param {*} wechatId 
 */
export async function getWxAccessToken(wechat_id, cb) {
    for (let index = 0, len = activeAccessTokens.length; index < len; index++) {
        const accessToken = activeAccessTokens[index];
        if (accessToken && accessToken.wechat_id === wechat_id) {
            const nowTime = Math.floor(new Date().getTime() / 1000);
            if (nowTime < accessToken.expire_time) {
                console.info(`wechat_id${wechat_id}, 有效的token:${accessToken.token}`);
                return cb(accessToken.token);
            }
        }
    }

    // 获取对应的配置信息
    let config = null;
    for (let index = 0, len = publicPlatfromList.length; index < len; index++) {
        const item = publicPlatfromList[index];
        if (item && parseInt(item.wechat_id, 10) === parseInt(wechat_id, 10)) {
            config = item;
            break;
        }
    }

    if (!config) {
        console.error('未知的公众号信息');
        return cb('');
    }

    // 队列获取
    eventMap.get(wechat_id).once('end', cb);
    if (eventMap.get(wechat_id + STATE_PREFIX) === 'ready') {
        eventMap.set(wechat_id + STATE_PREFIX, 'pending');
        // 请求微信获取对应的token
        console.log(`app_id:${config.app_id}, app_secret:${config.app_secret}`)
        // const result = await getWeiXinToken(config.app_id, config.app_secret);
        const result = await getWeiXinTokenFromLocal(config.app_id, config.app_secret, wechat_id);
        if (result) {
            const json = evil(result);
            // 过期时间
            const nowTime = Math.floor(new Date().getTime() / 1000) + json.expires_in;
            const wx_access_token = {
                wechat_id: wechat_id,
                token: json.access_token || '',
                expire_time: nowTime
            };
            // 替换之前的AccessToken
            let notFind = true;
            for (let i = 0; i < activeAccessTokens.length; i++) {
                if (activeAccessTokens[i] && activeAccessTokens[i].wechat_id === wx_access_token.wechat_id) {
                    activeAccessTokens[i] = wx_access_token;
                    notFind = false;
                    break;
                }
            }
            if (notFind) {
                activeAccessTokens.push(wx_access_token);
            }
            console.info(`wechat_id:${wechat_id}, 获取最新的AccessToken:${json.access_token || ''}`);
            eventMap.get(wechat_id).emit('end', json.access_token || '');
            eventMap.set(wechat_id + STATE_PREFIX, 'ready');
        } else {
            eventMap.get(wechat_id).emit('end', '');
            eventMap.set(wechat_id + STATE_PREFIX, 'ready');
        }

    }
}


/**
 * 获取微信的token
 * @param {} appId 
 * @param {*} secret 
 */
function getWeiXinToken(appId, secret) {
    return new Promise(function (resolve, reject) {
        const url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + appId + '&secret=' + secret;
        request(url, function (error, resp, json) {
            if (error) {
                resolve('');
            } else {
                resolve(json);
            }
        })
    })
}

function evil(fn) {
    let Fn = Function;
    return new Fn('return ' + fn)();
}


/**
 * 初始化Airkiss必要参数
 * @param {*} appid 
 * @param {*} token 
 * @param {*} url 
 */
export function getTicket(appid, token, url) {
    return new Promise(function (resolve, reject) {
        // 精确到秒
        const timestamp = Math.floor(Date.now() / 1000) + '';
        const NONCESTR = Math.random().toString(36).substr(2, 15);
        request('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + token + '&type=jsapi', function (error, resp, json) {
            if (error || resp.statusCode !== 200) {
                resolve('');
                sendLogToEmail(error);
            } else {
                const ticketMap = JSON.parse(json);
                const data = {
                    access_token: token,
                    nonceStr: NONCESTR,
                    appId: appid,
                    timestamp: timestamp,
                    url: url,
                    jsapi_ticket: ticketMap.ticket,
                    signature: sha1('jsapi_ticket=' + ticketMap.ticket + '&noncestr=' + NONCESTR + '&timestamp=' + timestamp + '&url=' + url)
                };
                console.info(`signature:${data.signature}`);
                resolve(data);
            }
        })
    })
}

// 程序启动必须调用该函数
export async function loadPublicPlatforms(cb) {
    const sql = 'SELECT `wechat_id`,`app_id`,`app_secret`,`host`,`company_name`,`device_name`,`device_type`,`template_id`,`bind_img_name` FROM  `wechat_manage`';
    try {
        const { err, result } = await exesql(sql, []);
        if (err) {
            sendLogToEmail('*****加载公众号信息异常****,' + err.stack);
            return;
        }

        if (result.length === 0) {
            sendLogToEmail('*****没有找到公众号配置信息****');
            return;
        }
        eventMap.clear();
        result.forEach(row => {
            // 保存到redis
            // savePublicPlatfrom(row);
            // 初始化事件
            const wechat_id = row.wechat_id;
            if (!eventMap.has(wechat_id)) {
                let event = new events.EventEmitter();
                event.setMaxListeners(0);
                eventMap.set(wechat_id, event);
                eventMap.set(wechat_id + STATE_PREFIX, 'ready');
            }
        });
        publicPlatfromList = result;
        console.log(`[workder]:加载的公众号个数:${eventMap.size / 2}`);
        cb();
    } catch (err) {
        sendLogToEmail('*****加载公众号信息异常****,' + err.stack);
    }

}


/**
 * 获取公众号配置信息
 */
export function getWechatPublicPlatformById(wechat_id) {
    for (let index = 0, len = publicPlatfromList.length; index < len; index++) {
        const config = publicPlatfromList[index];
        if (parseInt(config.wechat_id, 10) === parseInt(wechat_id, 10)) {
            return config;
        }
    }
    return null;
}

/**
 * 获取wechatId
 */
export function getWechatIdBySn(deviceSn) {
    for (let index = 0, len = publicPlatfromList.length; index < len; index++) {
        const config = publicPlatfromList[index];
        if (deviceSn.indexOf(config.device_type) >= 0) {
            return config.wechat_id;
        }
    }
    return 0;
}

/**
 * 根据序列号获取对应的公众号信息
 */
export function getWechatPublicPlatformBySn(deviceSn) {
    for (let index = 0, len = publicPlatfromList.length; index < len; index++) {
        const config = publicPlatfromList[index];
        if (deviceSn.indexOf(config.device_type) >= 0) {
            return config;
        }
    }
    return null;
}

export function removeWxToken(accessToken) {
    for (let i = 0; i < activeAccessTokens.length; i++) {
        if (activeAccessTokens[i].token === accessToken) {
            activeAccessTokens[i].expire_time = 0;
            console.info(`清除:${activeAccessTokens[i].wechat_id}对应的Token过期`);
            break;
        }
    }
}


/**
 * 获取微信的token
 * @param {} appId 
 * @param {*} secret 
 * @param{微信公众号id} wechatId
 */
function getWeiXinTokenFromLocal(appId, secret,wechatId) {
    return new Promise(function (resolve, reject) {
        const url = 'http://' + LOCAL_HTTP_SERVER + ':' + LOCAL_HTTP_PORT + '/wx_token/?app_id=' + appId + '&app_secret=' + secret + '&worker_id=' + cluster.worker.id + '&wechat_id='+wechatId;
        const options = {
            uri:url,
            method: 'GET',
            timeout: 10000,
        };
        request(options, function (error, resp, json) {
            if (error) {
                console.log(error);
                resolve('');
            } else {
                resolve(json);
            }
        })
    })
}